package com.szwistar.common.comm;

import com.szwistar.common.datastruct.JsonObject;
import com.szwistar.common.datastruct.Utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 解析 HTTP 请求中 "multipart/form-data" 类型的 body
 */
public class HttpMultipartBodyParser {
	// 头部结束标识是2个"\r\n"
	static final byte[] CRLF2 = new byte[] {0x0D, 0x0A, 0x0D, 0x0A};

	private static class RawPart {
		int begin;
		int end;

		public RawPart(int begin, int end) {
			super();
			this.begin = begin;
			this.end = end;
		}
	}

	public static class PartInfo {
		public String name;
		public String filename;
		public String contentType;
		public byte[] data;

		public PartInfo(String name, String filename, String contentType, byte[] data) {
			super();
			this.name = name;
			this.filename = filename;
			this.contentType = contentType;
			this.data = data;
		}
	}

	byte[] boundary;
	byte[] body;
	List<RawPart> rawParts = new ArrayList<RawPart>();

    public HttpMultipartBodyParser(byte[] body, byte[] boundary) {
		super();
		this.boundary = boundary;
		this.body = body;
	}

	// 解析下一个 part 的起始、结束位置
	private int parseNextRawPart(int offset) {
    	// 查找 boundary 开始位置
    	int pb = Utils.bytesIndexOf(body, offset, boundary);
    	// 如果没找到，则吃掉所有数据
    	if(pb < 0) { return body.length; }
    	// 开始位置跳到 part 的头部
    	pb += boundary.length + 2;
    	// 已经结束
    	if(pb >= body.length) { return body.length; }

    	// 查找 boundary 结束位置
    	int pe = Utils.bytesIndexOf(body, pb, boundary);
    	// 如果没找到，则吃掉所有数据
    	if(pe < 0) { return body.length; }
    	// 结束位置移到 "\r\n--" 前面
    	pe -= 4;

    	// 添加到 parts
    	rawParts.add(new RawPart(pb, pe));

		return pe;
    }

	// 解析各个 part 的起始、结束位置
	private int parseRawParts() {
		int offset = 0;
		do {
			offset = parseNextRawPart(offset);
		} while(offset < body.length);
		return rawParts.size();
	}

	// 解析指定 part 的内容
	private PartInfo parsePartInfo(RawPart rawPart) {
		// 查找 part 头部结束位置
    	int he = Utils.bytesIndexOf(body, rawPart.begin, CRLF2);
    	if(he < 0) { return null; }
    	// 数据开始位置
    	int pdata = he + 4;

    	// 头部信息字符串
    	String head = new String(Utils.bytesSlice(body, rawPart.begin, he - rawPart.begin));
    	String[] headParts = Utils.split(head, "[:;= \r\n]");
    	JsonObject info = new JsonObject((Object[])headParts);

		if(info.getStr("name", null) != null) {
			info.put("name", info.getStr("name", null).replaceAll("\"", ""));
		}
		if(info.getStr("filename", null) != null) {
			info.put("filename", info.getStr("filename", null).replaceAll("\"", ""));
		}

		// 保存数据为原始数据 byte[] 类型原始数据，由应用层对数据进行解析
		byte[] data = Utils.bytesSlice(body, pdata, rawPart.end - pdata);

		return new PartInfo(
			info.getStr("name", null),
			info.getStr("filename", null),
			info.getStr("Content-Type", null),
			data
		);
	}

	public static Map<String, PartInfo> parse(byte[] body, byte[] boundary) {
		Map<String, PartInfo> parts = new HashMap<String, PartInfo>();
		HttpMultipartBodyParser parser = new HttpMultipartBodyParser(body, boundary);

		// 解析各个 part 的起始、结束位置
		parser.parseRawParts();

		for(RawPart rawPart: parser.rawParts) {
			PartInfo part = parser.parsePartInfo(rawPart);
			if(part != null) { parts.put(part.name, part); }
		}

		return parts;
	}
}
